﻿// Copyright (c) 2012 - 2020 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2018-12-05 version 3.1.5 Jared Zheng <jaredz at outlook dot com>

#include "stdafx.h"
#include "datadef.h"
#include "ServerConfig.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// CServerConfig
CPCXStr CServerConfig::ServerConfig    = TF("ServerConfig");
CPCXStr CServerConfig::NetworkPtr      = TF("NetworkPtr");
                                       
CPCXStr CServerConfig::ConfigName      = TF("ServerConfig.cfg");
CPCXStr CServerConfig::ConfigServer    = TF("ConfigServer");
                                       
CPCXStr CServerConfig::NetworkConfig   = TF("NetworkConfig");
CPCXStr CServerConfig::NetworkAttr     = TF("NetworkAttr");
CPCXStr CServerConfig::NetworkThread   = TF("NetworkThread");
CPCXStr CServerConfig::NetworkAck      = TF("NetworkAck");
CPCXStr CServerConfig::NetworkTimeout  = TF("NetworkTimeout");
CPCXStr CServerConfig::NetworkBuffer   = TF("NetworkBuffer");
CPCXStr CServerConfig::NetworkJumbo    = TF("NetworkJumbo");
                                       
CPCXStr CServerConfig::ServersCommon   = TF("ServersCommon");
CPCXStr CServerConfig::UpdateTick      = TF("UpdateTick");
CPCXStr CServerConfig::StatTick        = TF("StatTick");
CPCXStr CServerConfig::AnyListen       = TF("AnyListen");
CPCXStr CServerConfig::InfoDump        = TF("InfoDump");
CPCXStr CServerConfig::LoadServers     = TF("LoadServers");
CPCXStr CServerConfig::CenterServer    = TF("CenterServer");
CPCXStr CServerConfig::BalanceServer   = TF("BalanceServer");
CPCXStr CServerConfig::AuthorDBServer  = TF("AuthorDBServer");
CPCXStr CServerConfig::AuthorServer    = TF("AuthorServer");
CPCXStr CServerConfig::MasterDBServer  = TF("MasterDBServer");
CPCXStr CServerConfig::MasterServer    = TF("MasterServer");
CPCXStr CServerConfig::ServiceServer   = TF("ServiceServer");
CPCXStr CServerConfig::GateServer      = TF("GateServer");

CPCXStr CServerConfig::CenterRoutine   = TF("CenterRoutine");
CPCXStr CServerConfig::BalanceRoutine  = TF("BalanceRoutine");
CPCXStr CServerConfig::AuthorDBRoutine = TF("AuthorDBRoutine");
CPCXStr CServerConfig::AuthorRoutine   = TF("AuthorRoutine");
CPCXStr CServerConfig::MasterDBRoutine = TF("MasterDBRoutine");
CPCXStr CServerConfig::MasterRoutine   = TF("MasterRoutine");
CPCXStr CServerConfig::ServiceRoutine  = TF("ServiceRoutine");
CPCXStr CServerConfig::GateRoutine     = TF("GateRoutine");

CPCXStr CServerConfig::Value           = TF("Value");
CPCXStr CServerConfig::Internal        = TF("Internal");
CPCXStr CServerConfig::External        = TF("External");
CPCXStr CServerConfig::Ip              = TF("Ip");
CPCXStr CServerConfig::Port            = TF("Port");
CPCXStr CServerConfig::Id              = TF("Id");
CPCXStr CServerConfig::Incr            = TF("Incr");
CPCXStr CServerConfig::ExtConfig       = TF("ExtConfig");
CPCXStr CServerConfig::LocalHost       = TF("localhost");
CPCXStr CServerConfig::AddrAnyV4       = TF("0.0.0.0");
CPCXStr CServerConfig::AddrAnyV6       = TF("::");
CPCXStr CServerConfig::LogFolder       = TF("Log");
CPCXStr CServerConfig::CurFolder       = TF("./");
CPCXStr CServerConfig::LibPrefix       = TF("lib");
#ifdef __RUNTIME_DEBUG__
    #if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)
        CPCXStr CServerConfig::LibExt              = TF("D.dll");
        XChar   CServerConfig::PathSepChar         = TF('\\');
    #elif (__PLATFORM_TARGET__ == PLATFORM_TARGET_LINUX)
        CPCXStr CServerConfig::LibExt              = TF("D.so");
        XChar   CServerConfig::PathSepChar         = TF('/');
    #endif
#else
    #if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)
        CPCXStr CServerConfig::LibExt              = TF(".dll");
        XChar   CServerConfig::PathSepChar         = TF('\\');
    #elif (__PLATFORM_TARGET__ == PLATFORM_TARGET_LINUX)
        CPCXStr CServerConfig::LibExt              = TF(".so");
        XChar   CServerConfig::PathSepChar         = TF('/');
    #endif
#endif

void CServerConfig::SetArgs(PCXStr pszCmd)
{
    m_strArgv.RemoveAll();

    CString strKey;
    CString strValue;

    PXStr pszToken = nullptr;
    PXStr pszArg   = CXChar::Tok((PXStr)pszCmd, TF(" "), pszToken);
    while (pszArg != nullptr)
    {
        if (pszArg[0] == TF('-'))
        {
            ++pszArg;
            PCXStr pszSep = CXChar::Chr(pszArg, TF(':'));
            if (pszSep != nullptr)
            {
                strKey.FillBuffer(pszArg, (pszSep - pszArg));
                strValue = (pszSep + 1);

                DEV_DUMP(TF("SetArgs -%s:%s"), *strKey, *strValue);

                m_strArgv.Add(std::move(strKey), std::move(strValue));
            }
        }
        pszArg = CXChar::Tok(nullptr, TF(" "), pszToken);
    }
    // -ServerConfig:test.txt
    //----------------------------------
    // -NetworkThread:1
    // -NetworkAck:8000
    // -NetworkTimeout:80000
    // -NetworkBuffer:8000
    // -NetworkJumbo:64000
    //----------------------------------
    // -AnyListen:
    // -InfoDump:
    // -LoadServers:
    //----------------------------------
    // -ConfigServer0---N:GateSerevr
    // -Id0---N:
    // -Incr0---N:
    // -Value0---N:
    // -ExtConfig0---N:
    // -AuthorIp0---N:, -AuthorPort0---N:按对应服务器地址信息, 不需要传入的直接省略
}

void CServerConfig::SetArgs(Int nArgc, PXStr* ppszArgv)
{
    m_strArgv.RemoveAll();

    CString strKey;
    CString strValue;
    for (Int i = 1; i < nArgc; ++i)
    {
        PXStr pszArg = ppszArgv[i];
        if (pszArg[0] == TF('-'))
        {
            ++pszArg;
            PCXStr pszSep = CXChar::Chr(pszArg, TF(':'));
            if (pszSep != nullptr)
            {
                strKey.FillBuffer(pszArg, (pszSep - pszArg));
                strValue = (pszSep + 1);

                DEV_DUMP(TF("SetArgs -%s:%s"), *strKey, *strValue);
                m_strArgv.Add(std::move(strKey), std::move(strValue));
            }
        }
    }
}

bool CServerConfig::Init(void)
{
    bool bFullPath = false;
    if (m_strArgv.GetSize() > 0)
    {
        STR_ARGV_PAIR* pPair = m_strArgv.Find(ServerConfig);
        if (pPair != nullptr)
        {
            CString& strConfigName = pPair->m_V;
            if (strConfigName[0] == TF('\\'))
            { // 配置信息以\开始的表示是程序目录的相对路径
                m_strConfigName = strConfigName.GetBuffer(1);
            }
            else if ((strConfigName[0] == TF('.')) && (strConfigName[1] == TF('/')))
            { // 配置信息以./开始的表示是程序目录的相对路径
                m_strConfigName = strConfigName.GetBuffer(2);
            }
            else
            {
                m_strConfigName = strConfigName;
                bFullPath = true;
            }
        }
    }
    if (bFullPath == false)
    {
        m_FilePath.GetFullPath(CFilePath::ModulePath, m_strConfigName);
    }
    Int nPos = m_strConfigName.Find(PathSepChar, 0, true);
    if (nPos != -1)
    {
        m_strExtConfigPath  = m_strConfigName.Left(nPos + 1);
        m_strExtConfigPath += ExtConfig;

        m_strLogConfigPath  = m_strConfigName.Left(nPos + 1);
        m_strLogConfigPath += LogFolder;

        m_FilePath.CreateFolder(*m_strLogConfigPath);
    }
    else
    {
        m_strExtConfigPath  = ExtConfig;
        m_strLogConfigPath  = LogFolder;

        m_FilePath.CreateFolder(*m_strLogConfigPath, CFilePath::ModulePath);
    }
    m_strExtConfigPath += PathSepChar;

    CFileReadStream Reader;
    if (Reader.Create(*m_strConfigName))
    {
        CXMLDocument Config;
        if (Config.Load(Reader))
        {
            CXMLNode* pRoot = Config.Find(ServerConfig);
            if (pRoot != nullptr)
            {
                LoadConfig(pRoot);
            }
            else
            {
                DEV_WARN(TF("读取配置文件[%s]失败!"), *m_strConfigName);
            }
        }
        else
        {
            DEV_WARN(TF("解析配置文件[%s]失败!"), *m_strConfigName);
        }
    }
    else
    {
        DEV_WARN(TF("加载配置文件[%s]失败!"), *m_strConfigName);
    }
    CheckConfig();

    CPlatform::SetLocal(LC_ALL, TF("chs")); // 支持简体中文日志

    m_KeyValue.AddItem(ServerConfig, (void*)this);
    return true;
}

void CServerConfig::Update(void)
{
    ResetNetwork();
    ResetServerCommon();

    ResetCenterServer();
    ResetBalanceServer();
    ResetAuthorDBServer();
    ResetAuthorServer();
    ResetMasterDBServer();
    ResetMasterServer();
    ResetServiceServer();
    ResetGateServer();

    CFileReadStream Reader;
    if (Reader.Create(*m_strConfigName))
    {
        CXMLDocument Config;
        if (Config.Load(Reader))
        {
            CXMLNode* pRoot = Config.Find(ServerConfig);
            if (pRoot != nullptr)
            {
                LoadConfig(pRoot);
            }
        }
    }
    CheckConfig();
}

void CServerConfig::Exit(void)
{
    //m_KeyValue.Remove(ServerConfig);
}

void CServerConfig::Dump(CFileLog& Log, Int nServer)
{
    LOG_DUMP(Log, *m_strConfigName);
    LOGV_DUMP(Log, TF("[%s]%s=%d, %s=%d, %s=%d, %s=%d, %s=%d, %s=%d"), NetworkConfig, 
              NetworkAttr,    m_nNetworkAttr, 
              NetworkThread,  m_nNetworkThread,
              NetworkAck,     m_nNetworkAck,
              NetworkTimeout, m_nNetworkTimeout,
              NetworkBuffer,  m_nNetworkBuffer,
              NetworkJumbo,   m_nNetworkJumbo);

    LOGV_DUMP(Log, TF("[%s]%s=%d[S], %s=%d[S], %s=%d, %s=%d, %s=%X"), ServersCommon,
              UpdateTick,   m_nUpdateTick,
              StatTick,     m_nStatTick,
              AnyListen,    m_nAnyListen,
              InfoDump,     m_nInfoDump,
              LoadServers,  m_nLoadServers);

    if (nServer & CFG_LOAD_CENTER)
    {
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d]"), CenterServer,
                  LoadServers, *m_strCenterServerPath,
                  Id,           m_nCenterServerId,
                  Incr,         m_nCenterServerIncr,
                  Value,        m_nCenterServerValue,
                  ExtConfig,   *m_strCenterServerExtConfig,
                  Internal,    *m_CenterServer4.strIp, m_CenterServer4.usPort);
    }
    if (nServer & CFG_LOAD_BALANCE)
    {
        if ((nServer & CFG_LOAD_CENTER) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), CenterServer, Internal, *m_CenterServer4.strIp, m_CenterServer4.usPort);
        }
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d]"), BalanceServer,
                  LoadServers,  *m_strBalanceServerPath,
                  Id,            m_nBalanceServerId,
                  Incr,          m_nBalanceServerIncr,
                  Value,         m_nBalanceServerValue,
                  ExtConfig,    *m_strBalanceServerExtConfig,
                  CenterServer, *m_BalanceServer2.strIp, m_BalanceServer2.usPort,
                  External,     *m_BalanceServer4.strIp, m_BalanceServer4.usPort);
    }
    if (nServer & CFG_LOAD_AUTHORDB)
    {
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d]"), AuthorDBServer,
                  LoadServers,    *m_strAuthorDBServerPath,
                  Id,              m_nAuthorDBServerId,
                  Incr,            m_nAuthorDBServerIncr, 
                  Value,           m_nAuthorDBServerValue,
                  ExtConfig,      *m_strAuthorDBServerExtConfig,
                  CenterServer,   *m_AuthorDBServer2.strIp, m_AuthorDBServer2.usPort,
                  Internal,       *m_AuthorDBServer4.strIp, m_AuthorDBServer4.usPort);
    }
    if (nServer & CFG_LOAD_AUTHOR)
    {
        if ((nServer & (CFG_LOAD_CENTER|CFG_LOAD_BALANCE)) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), CenterServer, Internal, *m_CenterServer4.strIp, m_CenterServer4.usPort);
        }
        if ((nServer & CFG_LOAD_AUTHORDB) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), AuthorDBServer, Internal, *m_AuthorDBServer4.strIp, m_AuthorDBServer4.usPort);
        }
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d], %s=%s[%d], %s=%s[%d]"), AuthorServer,
                  LoadServers,    *m_strAuthorServerPath,
                  Id,              m_nAuthorServerId,
                  Incr,            m_nAuthorServerIncr,
                  Value,           m_nAuthorServerValue,
                  ExtConfig,      *m_strAuthorServerExtConfig,
                  CenterServer,   *m_AuthorServer2Center.strIp,   m_AuthorServer2Center.usPort,
                  AuthorDBServer, *m_AuthorServer2AuthorDB.strIp, m_AuthorServer2AuthorDB.usPort,
                  MasterServer,   *m_AuthorServer4Master.strIp,   m_AuthorServer4Master.usPort,
                  External,       *m_AuthorServer4External.strIp, m_AuthorServer4External.usPort);
    }
    if (nServer & CFG_LOAD_MASTERDB)
    {
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d]"), MasterDBServer,
                  LoadServers,    *m_strMasterDBServerPath,
                  Id,              m_nMasterDBServerId,
                  Incr,            m_nMasterDBServerIncr,
                  Value,           m_nMasterDBServerValue,
                  ExtConfig,      *m_strMasterDBServerExtConfig,
                  CenterServer,   *m_MasterDBServer2.strIp, m_MasterDBServer2.usPort,
                  Internal,       *m_MasterDBServer4.strIp, m_MasterDBServer4.usPort);
    }
    if (nServer & CFG_LOAD_MASTER)
    {
        if ((nServer & (CFG_LOAD_CENTER|CFG_LOAD_BALANCE|CFG_LOAD_AUTHOR)) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), CenterServer, Internal, *m_CenterServer4.strIp, m_CenterServer4.usPort);
        }
        if ((nServer & CFG_LOAD_MASTERDB) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), MasterDBServer, Internal, *m_MasterDBServer4.strIp, m_MasterDBServer4.usPort);
        }
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d], %s=%s[%d], %s=%s[%d]"), MasterServer,
                  LoadServers,    *m_strMasterServerPath,
                  Id,              m_nMasterServerId,
                  Incr,            m_nMasterServerIncr,
                  Value,           m_nMasterServerValue,
                  ExtConfig,      *m_strMasterServerExtConfig,
                  CenterServer,   *m_MasterServer2Center.strIp,   m_MasterServer2Center.usPort,
                  MasterDBServer, *m_MasterServer2MasterDB.strIp, m_MasterServer2MasterDB.usPort,
                  AuthorServer,   *m_MasterServer4Author.strIp,   m_MasterServer4Author.usPort,
                  Internal,       *m_MasterServer4.strIp,         m_MasterServer4.usPort);
    }
    if (nServer & CFG_LOAD_SERVICE)
    {
        if ((nServer & CFG_LOAD_MASTER) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), MasterServer, Internal, *m_MasterServer4.strIp, m_MasterServer4.usPort);
            if ((nServer & CFG_LOAD_MASTERDB) == 0)
            {
                LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), MasterDBServer, Internal, *m_MasterDBServer4.strIp, m_MasterDBServer4.usPort);
            }
        }
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d]"), ServiceServer,
                  LoadServers,    *m_strServiceServerPath,
                  Id,              m_nServiceServerId,
                  Incr,            m_nServiceServerIncr,
                  Value,           m_nServiceServerValue,
                  ExtConfig,      *m_strServiceServerExtConfig,
                  MasterServer,   *m_ServiceServer2Master.strIp,   m_ServiceServer2Master.usPort,
                  MasterDBServer, *m_ServiceServer2MasterDB.strIp, m_ServiceServer2MasterDB.usPort);
    }
    if (nServer & CFG_LOAD_GATE)
    {
        if ((nServer & (CFG_LOAD_MASTER|CFG_LOAD_SERVICE)) == 0)
        {
            LOGV_DUMP(Log, TF("[%s]%s=%s[%d]"), MasterServer, Internal, *m_MasterServer4.strIp, m_MasterServer4.usPort);
        }
        LOGV_DUMP(Log, TF("[%s]%s=%s, %s=%d, %s=%d, %s=%d, %s=%s, %s=%s[%d], %s=%s[%d], %s=%s[%d]"), GateServer,
                  LoadServers,  *m_strGateServerPath,
                  Id,            m_nGateServerId,
                  Incr,          m_nGateServerIncr,
                  Value,         m_nGateServerValue,
                  ExtConfig,    *m_strGateServerExtConfig,
                  MasterServer, *m_GateServer2.strIp,         m_GateServer2.usPort,
                  AuthorServer, *m_GateServer4Author.strIp,   m_GateServer4Author.usPort,
                  External,     *m_GateServer4External.strIp, m_GateServer4External.usPort);
    }
    if (m_strArgv.GetSize() > 0)
    {
        LOGV_DUMP(Log, TF("Args count=%d"), m_strArgv.GetSize());
        Int nCount = 0;
        for (PINDEX index = m_strArgv.GetFirstIndex(); index != nullptr;)
        {
            STR_ARGV_PAIR* pPair = m_strArgv.GetNext(index);
            LOGV_DUMP(Log, TF("%d-th Arg -%s:%s"), nCount, *pPair->m_K, *pPair->m_V);
            ++nCount;
        }
    }
    else
    {
        LOG_DUMP(Log, TF("Args is empty!"));
    }
}

bool CServerConfig::LoadConfig(CXMLNode* pRoot)
{
    LoadNetwork(pRoot);
    LoadServersCommon(pRoot);

    LoadCenterServer(pRoot);
    LoadBalanceServer(pRoot);
    LoadAuthorDBServer(pRoot);
    LoadAuthorServer(pRoot);
    LoadMasterDBServer(pRoot);
    LoadMasterServer(pRoot);
    LoadServiceServer(pRoot);
    LoadGateServer(pRoot);
    return true;
}

bool CServerConfig::LoadNetwork(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(NetworkConfig);
    if (pSection != nullptr)
    {
        LoadValue(pSection, NetworkAttr,    Value, m_nNetworkAttr);
        LoadValue(pSection, NetworkThread,  Value, m_nNetworkThread);
        LoadValue(pSection, NetworkAck,     Value, m_nNetworkAck);
        LoadValue(pSection, NetworkTimeout, Value, m_nNetworkTimeout);
        LoadValue(pSection, NetworkBuffer,  Value, m_nNetworkBuffer);
        LoadValue(pSection, NetworkJumbo,   Value, m_nNetworkJumbo);
        return true;
    }
    return false;
}

bool CServerConfig::LoadServersCommon(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(ServersCommon);
    if (pSection != nullptr)
    {
        LoadValue(pSection, UpdateTick, Value, m_nUpdateTick);
        m_nUpdateTick = DEF::Max<Int>(m_nUpdateTick, CFG_UPDATE_MIN_TIME);

        LoadValue(pSection, StatTick,   Value, m_nStatTick);
        DEF::Maxmin<Int>(m_nStatTick, CFG_STAT_MIN_TIME, CFG_STAT_MAX_TIME);
        m_nStatTick /= CFG_STAT_MIN_TIME;
        m_nStatTick *= CFG_STAT_MIN_TIME; // 统计时间间隔是15分钟周期的倍数
        // 同步更新周期不能大于统计上报周期
        m_nUpdateTick = DEF::Min<Int>(m_nUpdateTick, m_nStatTick);


        LoadValue(pSection, AnyListen,  Value, m_nAnyListen);
        LoadValue(pSection, InfoDump,   Value, m_nInfoDump);
        
        CStringFix strValue;
        LoadValue(pSection, LoadServers, Value, strValue);
        LoadServersCommon(strValue);

        LoadValue(pSection, CenterServer,   Value, m_strCenterServerPath);
        LoadValue(pSection, BalanceServer,  Value, m_strBalanceServerPath);
        LoadValue(pSection, AuthorDBServer, Value, m_strAuthorDBServerPath);
        LoadValue(pSection, AuthorServer,   Value, m_strAuthorServerPath);
        LoadValue(pSection, MasterDBServer, Value, m_strMasterDBServerPath);
        LoadValue(pSection, MasterServer,   Value, m_strMasterServerPath);
        LoadValue(pSection, ServiceServer,  Value, m_strServiceServerPath);
        LoadValue(pSection, GateServer,     Value, m_strGateServerPath);
        return true;
    }
    return false;
}

bool CServerConfig::LoadCenterServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(CenterServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nCenterServerId, m_nCenterServerIncr, m_nCenterServerValue, m_strCenterServerExtConfig);
        LoadServerAddr(pSection, Internal, m_CenterServer4);
        return true;
    }
    return false;
}

bool CServerConfig::LoadBalanceServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(BalanceServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nBalanceServerId, m_nBalanceServerIncr, m_nBalanceServerValue, m_strBalanceServerExtConfig);
        LoadServerAddr(pSection, CenterServer, m_BalanceServer2);
        LoadServerAddr(pSection, External,     m_BalanceServer4);
        return true;
    }
    return false;
}

bool CServerConfig::LoadAuthorDBServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(AuthorDBServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nAuthorDBServerId, m_nAuthorDBServerIncr, m_nAuthorDBServerValue, m_strAuthorDBServerExtConfig);
        LoadServerAddr(pSection, CenterServer, m_AuthorDBServer2);
        LoadServerAddr(pSection, Internal,     m_AuthorDBServer4);
        return true;
    }
    return false;
}

bool CServerConfig::LoadAuthorServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(AuthorServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nAuthorServerId, m_nAuthorServerIncr, m_nAuthorServerValue, m_strAuthorServerExtConfig);
        LoadServerAddr(pSection, CenterServer,   m_AuthorServer2Center);
        LoadServerAddr(pSection, AuthorDBServer, m_AuthorServer2AuthorDB);
        LoadServerAddr(pSection, MasterServer,   m_AuthorServer4Master);
        LoadServerAddr(pSection, External,       m_AuthorServer4External);
        return true;
    }
    return false;
}

bool CServerConfig::LoadMasterDBServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(MasterDBServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nMasterDBServerId, m_nMasterDBServerIncr, m_nMasterDBServerValue, m_strMasterDBServerExtConfig);
        LoadServerAddr(pSection, CenterServer, m_MasterDBServer2);
        LoadServerAddr(pSection, Internal,     m_MasterDBServer4);
        return true;
    }
    return false;
}

bool CServerConfig::LoadMasterServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(MasterServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nMasterServerId, m_nMasterServerIncr, m_nMasterServerValue, m_strMasterServerExtConfig);
        LoadServerAddr(pSection, CenterServer,   m_MasterServer2Center);
        LoadServerAddr(pSection, MasterDBServer, m_MasterServer2MasterDB);
        LoadServerAddr(pSection, AuthorServer,   m_MasterServer4Author);
        LoadServerAddr(pSection, Internal,       m_MasterServer4);
        return true;
    }
    return false;
}

bool CServerConfig::LoadServiceServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(ServiceServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nServiceServerId, m_nServiceServerIncr, m_nServiceServerValue, m_strServiceServerExtConfig);
        LoadServerAddr(pSection, MasterServer,   m_ServiceServer2Master);
        LoadServerAddr(pSection, MasterDBServer, m_ServiceServer2MasterDB);
        return true;
    }
    return false;
}

bool CServerConfig::LoadGateServer(CXMLNode* pRoot)
{
    CXMLNode* pSection = pRoot->Find(GateServer);
    if (pSection != nullptr)
    {
        LoadServerAttr(pSection, m_nGateServerId, m_nGateServerIncr, m_nGateServerValue, m_strGateServerExtConfig);
        LoadServerAddr(pSection, MasterServer, m_GateServer2);
        LoadServerAddr(pSection, AuthorServer, m_GateServer4Author);
        LoadServerAddr(pSection, External,     m_GateServer4External);
        return true;
    }
    return false;
}

bool CServerConfig::LoadServersCommon(CStringFix& strFixValue)
{
    m_nLoadServers = 0;
    if (strFixValue.Find(CenterServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_CENTER;
    }
    if (strFixValue.Find(BalanceServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_BALANCE;
    }
    if (strFixValue.Find(AuthorDBServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_AUTHORDB;
    }
    if (strFixValue.Find(AuthorServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_AUTHOR;
    }
    if (strFixValue.Find(MasterDBServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_MASTERDB;
    }
    if (strFixValue.Find(MasterServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_MASTER;
    }
    if (strFixValue.Find(ServiceServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_SERVICE;
    }
    if (strFixValue.Find(GateServer) != -1)
    {
        m_nLoadServers |= CFG_LOAD_GATE;
    }
    return true;
}

bool CServerConfig::LoadValue(CXMLNode* pSection, PCXStr pszElement, PCXStr pszAttr, Int& nValue)
{
    CXMLNode* pNode = pSection->Find(pszElement);
    if (pNode != nullptr)
    {
        CXMLElement* pElement = pNode->To<CXMLElement, CXMLTraits::XMLT_ELEMENT>();
        return pElement->GetAttribute(pszAttr, nValue);
    }
    return false;
}

bool CServerConfig::LoadValue(CXMLNode* pSection, PCXStr pszElement, PCXStr pszAttr, CStringFix& strFixValue)
{
    CXMLNode* pNode = pSection->Find(pszElement);
    if (pNode != nullptr)
    {
        CXMLElement* pElement = pNode->To<CXMLElement, CXMLTraits::XMLT_ELEMENT>();
        CTStringFix<CXmlChar, (size_t)LMT_MAX_PATH>* pstrTemp = reinterpret_cast<CTStringFix<CXmlChar, (size_t)LMT_MAX_PATH>*>(&strFixValue);
        return pElement->GetAttribute<(size_t)LMT_MAX_PATH>(pszAttr, *pstrTemp);
    }
    return false;
}

bool CServerConfig::LoadServerAttr(CXMLNode* pSection, Int& nId, Int& nIncr, Int& nValue, CStringFix& strFixExtConfig)
{
    CXMLElement* pElement = pSection->To<CXMLElement, CXMLTraits::XMLT_ELEMENT>();
    if (pElement != nullptr)
    {
        pElement->GetAttribute(Id, nId);
        pElement->GetAttribute(Incr, nIncr);
        pElement->GetAttribute(Value, nValue);

        CTStringFix<CXmlChar, (size_t)LMT_MAX_PATH>* pstrTemp = reinterpret_cast<CTStringFix<CXmlChar, (size_t)LMT_MAX_PATH>*>(&strFixExtConfig);
        pElement->GetAttribute<(size_t)LMT_MAX_PATH>(ExtConfig, *pstrTemp);
        return true;
    }
    return false;
}

bool CServerConfig::LoadServerAttr(Int& nId, Int& nIncr, Int& nValue, CStringFix& strFixExtConfig, Int nIndex)
{
    CString strIndex;
    strIndex.ToString(nIndex);

    CString strKey = Id;
    strKey += strIndex;

    STR_ARGV_PAIR* pPair = m_strArgv.Find(strKey);
    if (pPair != nullptr)
    {
        nId = pPair->m_V.ToInt();
    }

    strKey = Incr;
    strKey += strIndex;
    pPair = m_strArgv.Find(strKey);
    if (pPair != nullptr)
    {
        nIncr = pPair->m_V.ToInt();
    }

    strKey = Value;
    strKey += strIndex;
    pPair = m_strArgv.Find(strKey);
    if (pPair != nullptr)
    {
        nValue = pPair->m_V.ToInt();
    }

    strKey = ExtConfig;
    strKey += strIndex;
    pPair = m_strArgv.Find(strKey);
    if (pPair != nullptr)
    {
        strFixExtConfig = pPair->m_V;
    }
    return true;
}

bool CServerConfig::LoadServerAddr(CXMLNode* pSection, PCXStr pszServer, CStrAddr& strAddr)
{
    CXMLNode* pNode = pSection->Find(pszServer);
    if (pNode != nullptr)
    {
        CXMLElement* pElement = pNode->To<CXMLElement, CXMLTraits::XMLT_ELEMENT>();
        CXmlString* pstrTemp = reinterpret_cast<CXmlString*>(&(strAddr.strIp));
        pElement->GetAttribute(Ip, *pstrTemp);
        pElement->GetAttribute(Port, strAddr.usPort);
        return true;
    }
    return false;
}

bool CServerConfig::LoadServerAddr(PCXStr pszServer, CStrAddr& strAddr, Int nIndex)
{
    CString strIndex;
    strIndex.ToString(nIndex);

    CString strKey = pszServer;
    strKey += Ip;
    strKey += strIndex;
    STR_ARGV_PAIR* pPair = m_strArgv.Find(strKey);
    if (pPair != nullptr)
    {
        strAddr.strIp = pPair->m_V;
    }
    strKey  = pszServer;
    strKey += Port;
    strKey += strIndex;
    pPair = m_strArgv.Find(strKey);
    if (pPair != nullptr)
    {
        strAddr.usPort = (UShort)pPair->m_V.ToInt();
    }
    return true;
}

void CServerConfig::ResetNetwork(void)
{
    m_nNetworkAttr    = 0;
    m_nNetworkThread  = 0;
    m_nNetworkAck     = 0;
    m_nNetworkTimeout = 0;
    m_nNetworkBuffer  = 0;
    m_nNetworkJumbo   = 0;
}

void CServerConfig::ResetServerCommon(void)
{
    m_nUpdateTick  = CFG_UPDATE_DEF_TIME;
    m_nStatTick    = CFG_STAT_DEF_TIME;
    m_nAnyListen   = TRUE;
    m_nInfoDump    = TRUE;
    m_nLoadServers = CFG_LOAD_ALLSERVER;

    m_strCenterServerPath.Empty();
    m_strBalanceServerPath.Empty();
    m_strAuthorDBServerPath.Empty();
    m_strAuthorServerPath.Empty();
    m_strMasterDBServerPath.Empty();
    m_strMasterServerPath.Empty();
    m_strServiceServerPath.Empty();
    m_strGateServerPath.Empty();
}

void CServerConfig::ResetCenterServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_CenterServer4.Reset(LocalHost, CFG_CENTER_PORT);
        m_nCenterServerId = PAKT_CENTER;
        m_nCenterServerIncr = DATAD_INCR_LOAD;
        m_nCenterServerValue = 0;
        m_strCenterServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(Internal, m_CenterServer4, nIndex);
        LoadServerAttr(m_nCenterServerId, m_nCenterServerIncr, m_nCenterServerValue, m_strCenterServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetBalanceServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_BalanceServer2.Reset(LocalHost);
        m_BalanceServer4.Reset(LocalHost, CFG_BALANCE_PORT);
        m_nBalanceServerId    = PAKT_BALANCE;
        m_nBalanceServerIncr  = DATAD_INCR_LOAD;
        m_nBalanceServerValue = 0;
        m_strBalanceServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(CenterServer, m_BalanceServer2, nIndex);
        LoadServerAddr(External,     m_BalanceServer4, nIndex);
        LoadServerAttr(m_nBalanceServerId, m_nBalanceServerIncr, m_nBalanceServerValue, m_strBalanceServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetAuthorDBServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_AuthorDBServer2.Reset(LocalHost);
        m_AuthorDBServer4.Reset(LocalHost);
        m_nAuthorDBServerId    = PAKT_AUTHORDB;
        m_nAuthorDBServerIncr  = DATAD_INCR_LOAD;
        m_nAuthorDBServerValue = 1;
        m_strAuthorDBServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(CenterServer, m_AuthorDBServer2, nIndex);
        LoadServerAddr(Internal,     m_AuthorDBServer4, nIndex);
        LoadServerAttr(m_nAuthorDBServerId, m_nAuthorDBServerIncr, m_nAuthorDBServerValue, m_strAuthorDBServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetAuthorServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_AuthorServer2Center.Reset(LocalHost);
        m_AuthorServer2AuthorDB.Reset(LocalHost);
        m_AuthorServer4Master.Reset(LocalHost);
        m_AuthorServer4External.Reset(LocalHost, CFG_AUTHOR_PORT);
        m_nAuthorServerId    = PAKT_AUTHOR;
        m_nAuthorServerIncr  = DATAD_INCR_LOAD;
        m_nAuthorServerValue = 1;
        m_strAuthorServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(CenterServer,   m_AuthorServer2Center, nIndex);
        LoadServerAddr(AuthorDBServer, m_AuthorServer2AuthorDB, nIndex);
        LoadServerAddr(MasterServer,   m_AuthorServer4Master, nIndex);
        LoadServerAddr(External,       m_AuthorServer4External, nIndex);
        LoadServerAttr(m_nAuthorServerId, m_nAuthorServerIncr, m_nAuthorServerValue, m_strAuthorServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetMasterDBServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_MasterDBServer2.Reset(LocalHost);
        m_MasterDBServer4.Reset(LocalHost);
        m_nMasterDBServerId    = PAKT_MASTERDB;
        m_nMasterDBServerIncr  = DATAD_INCR_LOAD;
        m_nMasterDBServerValue = 1;
        m_strMasterDBServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(CenterServer, m_MasterDBServer2, nIndex);
        LoadServerAddr(Internal,     m_MasterDBServer4, nIndex);
        LoadServerAttr(m_nMasterDBServerId, m_nMasterDBServerIncr, m_nMasterDBServerValue, m_strMasterDBServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetMasterServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_MasterServer2Center.Reset(LocalHost);
        m_MasterServer2MasterDB.Reset(LocalHost);
        m_MasterServer4Author.Reset(LocalHost);
        m_MasterServer4.Reset(LocalHost, CFG_MASTER_PORT);
        m_nMasterServerId    = PAKT_MASTER;
        m_nMasterServerIncr  = DATAD_INCR_LOAD;
        m_nMasterServerValue = 0;
        m_strMasterServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(CenterServer,   m_MasterServer2Center, nIndex);
        LoadServerAddr(MasterDBServer, m_MasterServer2MasterDB, nIndex);
        LoadServerAddr(AuthorServer,   m_MasterServer4Author, nIndex);
        LoadServerAddr(Internal,       m_MasterServer4, nIndex);
        LoadServerAttr(m_nMasterServerId, m_nMasterServerIncr, m_nMasterServerValue, m_strMasterServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetServiceServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_ServiceServer2Master.Reset(LocalHost);
        m_ServiceServer2MasterDB.Reset(LocalHost);
        m_nServiceServerId    = PAKT_SERVICE;
        m_nServiceServerIncr  = DATAD_INCR_LOAD;
        m_nServiceServerValue = 0;
        m_strServiceServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(MasterServer,   m_ServiceServer2Master, nIndex);
        LoadServerAddr(MasterDBServer, m_ServiceServer2MasterDB, nIndex);
        LoadServerAttr(m_nServiceServerId, m_nServiceServerIncr, m_nServiceServerValue, m_strServiceServerExtConfig, nIndex);
    }
}

void CServerConfig::ResetGateServer(bool bReset, Int nIndex)
{
    if (bReset)
    {
        m_GateServer2.Reset(LocalHost);
        m_GateServer4Author.Reset(LocalHost);
        m_GateServer4External.Reset(LocalHost, CFG_GATE_PORT);
        m_nGateServerId    = PAKT_GATE;
        m_nGateServerIncr  = DATAD_INCR_LOAD;
        m_nGateServerValue = 0;
        m_strGateServerExtConfig.Empty();
    }
    else
    {
        LoadServerAddr(MasterServer,   m_GateServer2, nIndex);
        LoadServerAddr(AuthorServer,   m_GateServer4Author, nIndex);
        LoadServerAddr(External,       m_GateServer4External, nIndex);
        LoadServerAttr(m_nGateServerId, m_nGateServerIncr, m_nGateServerValue, m_strGateServerExtConfig, nIndex);
    }
}

void CServerConfig::CheckConfig(void)
{
    STR_ARGV_PAIR* pPair = m_strArgv.Find(NetworkThread);
    if (pPair != nullptr)
    {
        m_nNetworkThread = pPair->m_V.ToInt();
        m_nNetworkAttr  |= CNETTraits::ATTR_THREAD;
    }
    pPair = m_strArgv.Find(NetworkAck);
    if (pPair != nullptr)
    {
        m_nNetworkAck = pPair->m_V.ToInt();
        m_nNetworkAttr  |= CNETTraits::ATTR_ACK_TIME;
    }
    pPair = m_strArgv.Find(NetworkTimeout);
    if (pPair != nullptr)
    {
        m_nNetworkTimeout = pPair->m_V.ToInt();
        m_nNetworkAttr  |= CNETTraits::ATTR_TIMEOUT_TIME;
    }
    pPair = m_strArgv.Find(NetworkBuffer);
    if (pPair != nullptr)
    {
        m_nNetworkBuffer = pPair->m_V.ToInt();
        m_nNetworkAttr  |= CNETTraits::ATTR_MAX_BUFFER;
    }
    pPair = m_strArgv.Find(NetworkJumbo);
    if (pPair != nullptr)
    {
        m_nNetworkJumbo = pPair->m_V.ToInt();
        m_nNetworkAttr  |= CNETTraits::ATTR_MAX_JUMBOBUF;
    }
    //----------------------------------
    pPair = m_strArgv.Find(AnyListen);
    if (pPair != nullptr)
    {
        m_nAnyListen = pPair->m_V.ToInt();
    }
    pPair = m_strArgv.Find(InfoDump);
    if (pPair != nullptr)
    {
        m_nInfoDump  = pPair->m_V.ToInt();
    }
    pPair = m_strArgv.Find(LoadServers);
    if (pPair != nullptr)
    {
        CStringFix strValue = pPair->m_V;
        LoadServersCommon(strValue);
    }
    //----------------------------------
    CString strConfigServer;
    for (Int i = 0; i < CFG_LOAD_ALLCOUNT; ++i)
    {
        strConfigServer.Format(TF("%s%d"), ConfigServer, i);
        pPair = m_strArgv.Find(strConfigServer);
        if (pPair != nullptr)
        {
            if (pPair->m_V == CenterServer)
            {
                ResetCenterServer(false, i);
            }
            if (pPair->m_V == BalanceServer)
            {
                ResetBalanceServer(false, i);
            }
            if (pPair->m_V == AuthorDBServer)
            {
                ResetAuthorDBServer(false, i);
            }
            if (pPair->m_V == AuthorServer)
            {
                ResetAuthorServer(false, i);
            }
            if (pPair->m_V == MasterDBServer)
            {
                ResetMasterDBServer(false, i);
            }
            if (pPair->m_V == MasterServer)
            {
                ResetMasterServer(false, i);
            }
            if (pPair->m_V == ServiceServer)
            {
                ResetServiceServer(false, i);
            }
            if (pPair->m_V == GateServer)
            {
                ResetGateServer(false, i);
            }
        }
        else
        {
            break;
        }
    }

    CheckAddr(m_CenterServer4);

    CheckAddr(m_BalanceServer2, false);
    CheckAddr(m_BalanceServer4);

    CheckAddr(m_AuthorDBServer2, false);
    CheckAddr(m_AuthorDBServer4);

    CheckAddr(m_AuthorServer2Center, false);
    CheckAddr(m_AuthorServer2AuthorDB, false);
    CheckAddr(m_AuthorServer4Master);
    CheckAddr(m_AuthorServer4External);

    CheckAddr(m_MasterDBServer2, false);
    CheckAddr(m_MasterDBServer4);

    CheckAddr(m_MasterServer2Center, false);
    CheckAddr(m_MasterServer2MasterDB, false);
    CheckAddr(m_MasterServer4Author);
    CheckAddr(m_MasterServer4);

    CheckAddr(m_ServiceServer2Master, false);
    CheckAddr(m_ServiceServer2MasterDB, false);

    CheckAddr(m_GateServer2, false);
    CheckAddr(m_GateServer4Author);
    CheckAddr(m_GateServer4External);

    CheckExtConfig(m_strCenterServerExtConfig,   CenterServer);
    CheckExtConfig(m_strBalanceServerExtConfig,  BalanceServer);
    CheckExtConfig(m_strAuthorDBServerExtConfig, AuthorDBServer);
    CheckExtConfig(m_strAuthorServerExtConfig,   AuthorServer);
    CheckExtConfig(m_strMasterDBServerExtConfig, MasterDBServer);
    CheckExtConfig(m_strMasterServerExtConfig,   MasterServer);
    CheckExtConfig(m_strServiceServerExtConfig,  ServiceServer);
    CheckExtConfig(m_strGateServerExtConfig,     GateServer);

    CheckPath(m_strCenterServerPath,   CenterServer);
    CheckPath(m_strBalanceServerPath,  BalanceServer);
    CheckPath(m_strAuthorDBServerPath, AuthorDBServer);
    CheckPath(m_strAuthorServerPath,   AuthorServer);
    CheckPath(m_strMasterDBServerPath, MasterDBServer);
    CheckPath(m_strMasterServerPath,   MasterServer);
    CheckPath(m_strServiceServerPath,  ServiceServer);
    CheckPath(m_strGateServerPath,     GateServer);
}

void CServerConfig::CheckAddr(CStrAddr& strAddr, bool bListen)
{
    if (bListen && strAddr.strIp.IsEmpty())
    {
        strAddr.strIp = LocalHost;
        //if (m_nNetworkAttr & CNETTraits::ATTR_IPV6)
        //{
        //    strAddr.strIp = bListen ? AddrAnyV6 : LocalHost;
        //}
        //else
        //{
        //    strAddr.strIp = bListen ? AddrAnyV4 : LocalHost;
        //}
    }
}

void CServerConfig::CheckExtConfig(CStringFix& strExtConfig, PCXStr pszServer)
{
    if (strExtConfig.IsEmpty())
    {
        strExtConfig  = m_strExtConfigPath;
        strExtConfig += pszServer;
        strExtConfig +=TF(".cfg");
    }
    else if (strExtConfig[0] == TF('\\'))
    { 
        // 配置信息以\开始的表示是程序目录的相对路径
        CStringFix strTemp = strExtConfig.GetBuffer(1);
        strExtConfig  = m_strExtConfigPath;
        strExtConfig += strTemp;
        strExtConfig +=TF(".cfg");
    }
    else if ((strExtConfig[0] == TF('.')) && (strExtConfig[1] == TF('/')))
    { 
        // 配置信息以./开始的表示是程序目录的相对路径
        CStringFix strTemp = strExtConfig.GetBuffer(2);
        strExtConfig  = m_strExtConfigPath;
        strExtConfig += strTemp;
        strExtConfig +=TF(".cfg");
    }
    else
    {
        strExtConfig +=TF(".cfg");
    }
}

void CServerConfig::CheckPath(CStringFix& strPath, PCXStr pszServer)
{
#if (__PLATFORM_TARGET__ == PLATFORM_TARGET_WINDOWS)
    if (strPath.IsEmpty())
    {
        strPath  = CurFolder;
        strPath += pszServer;
    }
#elif (__PLATFORM_TARGET__ == PLATFORM_TARGET_LINUX)
    if (strPath.IsEmpty())
    {
        strPath  = CurFolder;
        strPath += LibPrefix;
        strPath += pszServer;
    }
#endif
    strPath += LibExt;
}
